package com.geeksaga.service;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.geeksaga.common.constant.SagaConstants;
import com.geeksaga.common.util.KeyGenerator;
import com.geeksaga.common.util.StringUtils;
import com.geeksaga.dao.BbsDao;
import com.geeksaga.dao.IpCountryDao;
import com.geeksaga.dao.IssueDao;
import com.geeksaga.dao.MemoDao;
import com.geeksaga.dao.SpecDao;
import com.geeksaga.domain.Bbs;
import com.geeksaga.domain.BbsType;
import com.geeksaga.domain.IpCountry;
import com.geeksaga.domain.Issue;
import com.geeksaga.domain.Memo;
import com.geeksaga.domain.Spec;

/**
 * @author newbie
 * @since 0.1
 */
@Service
public class MemoServiceImpl implements MemoService {
    
	protected static final Log logger = LogFactory.getLog(MemoServiceImpl.class);
	
    @Autowired private BbsDao bbsDao;
    @Autowired private SpecDao specDao;
    @Autowired private IssueDao issueDao;
    @Autowired private MemoDao memoDao;
    @Autowired private IpCountryDao ipCountryDao;
    
    /* (non-Javadoc)
     * @see com.geeksaga.service.BbsMemoService#add(com.geeksaga.domain.Bbs)
     */
    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    public Bbs add(Bbs bbs) throws DataAccessException {
        
    	IpCountry ipCountry = ipCountryDao.findByIp(bbs.getUserIp());
		bbs.setUserCountry((ipCountry == null) ? SagaConstants.IP_COUNTRY_NULL : ipCountry.getCountryTwo());
    	
        if(bbs.getMemoList() != null) {
            Iterator<Memo> iterator = bbs.getMemoList().iterator();
            while(iterator.hasNext()) {
                Memo memo = iterator.next();
                
                if(StringUtils.isEmpty(memo.getSid())) {
                    memo.setSid(KeyGenerator.generatorBbsKey());
                    memo.setDepth(SagaConstants.DEFAULT_DEPTH);
                } else {
                    memo.setDepth(String.valueOf(Integer.valueOf(memo.getDepth()) + 1));
                }
                
                memo.setMemoType("A00601");
                memo.setTargetSid(bbs.getSid());
                memo.setUserSid(bbs.getUserSid());
                memo.setUserIcon(bbs.getUserIcon());
                memo.setUserIp(bbs.getUserIp());
                memo.setUserCountry(bbs.getUserCountry());
                
                memoDao.add(memo);
                
                bbsDao.updateCnt(bbs, Bbs.CNT_TYPE.MEMO_PLUS_CNT);
            }
        }
        
        return bbs;
    }
    
    /* (non-Javadoc)
     * @see com.geeksaga.service.MemoService#add(com.geeksaga.domain.Spec)
     */
    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    public Spec add(Spec spec) throws DataAccessException {
    	
    	IpCountry ipCountry = ipCountryDao.findByIp(spec.getUserIp());
    	spec.setUserCountry((ipCountry == null) ? SagaConstants.IP_COUNTRY_NULL : ipCountry.getCountryTwo());
    	
    	if(spec.getMemoList() != null) {
    		Iterator<Memo> iterator = spec.getMemoList().iterator();
    		while(iterator.hasNext()) {
    			Memo memo = iterator.next();
    			
    			if(StringUtils.isEmpty(memo.getSid())) {
    				memo.setSid(KeyGenerator.generatorBbsKey());
    				memo.setDepth(SagaConstants.DEFAULT_DEPTH);
    			} else {
    				memo.setDepth(String.valueOf(Integer.valueOf(memo.getDepth()) + 1));
    			}
    			
    			memo.setMemoType("A00602");
    			memo.setTargetSid(spec.getSid());
    			memo.setUserSid(spec.getUserSid());
    			memo.setUserIcon(spec.getUserIcon());
    			memo.setUserIp(spec.getUserIp());
    			memo.setUserCountry(spec.getUserCountry());
    			
    			memoDao.add(memo);
    			
    			specDao.updateCnt(spec, Spec.CNT_TYPE.MEMO_PLUS_CNT);
    		}
    	}
    	
    	return spec;
    }
    
    /* (non-Javadoc)
     * @see com.geeksaga.service.MemoService#add(com.geeksaga.domain.Issue)
     */
    public Issue add(Issue issue) throws DataAccessException {
        
        IpCountry ipCountry = ipCountryDao.findByIp(issue.getUserIp());
        issue.setUserCountry((ipCountry == null) ? SagaConstants.IP_COUNTRY_NULL : ipCountry.getCountryTwo());
        
        if(issue.getMemoList() != null) {
            Iterator<Memo> iterator = issue.getMemoList().iterator();
            while(iterator.hasNext()) {
                Memo memo = iterator.next();
                
                if(StringUtils.isEmpty(memo.getSid())) {
                    memo.setSid(KeyGenerator.generatorBbsKey());
                    memo.setDepth(SagaConstants.DEFAULT_DEPTH);
                } else {
                    memo.setDepth(String.valueOf(Integer.valueOf(memo.getDepth()) + 1));
                }
                
                memo.setMemoType("A00603");
                memo.setTargetSid(issue.getSid());
                memo.setUserSid(issue.getUserSid());
                memo.setUserIcon(issue.getUserIcon());
                memo.setUserIp(issue.getUserIp());
                memo.setUserCountry(issue.getUserCountry());
                
                memoDao.add(memo);
                
                issueDao.updateCnt(issue, Issue.CNT_TYPE.MEMO_PLUS_CNT);
            }
        }
        
        return issue;
    }
    
    /* (non-Javadoc)
     * @see com.geeksaga.service.BbsMemoService#reply(com.geeksaga.domain.Bbs)
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor=Exception.class)
    public Bbs reply(Bbs bbs) throws DataAccessException {
        return reply(bbs, null);
    }
    
    /* (non-Javadoc)
     * @see com.geeksaga.service.MemoService#reply(com.geeksaga.domain.Spec)
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor=Exception.class)
    public Spec reply(Spec spec) throws DataAccessException {
        memoDao.updateReply(spec.getMemoList().get(0).getSid());
        
        spec.getMemoList().get(0).setSid(String.valueOf((Long.valueOf(spec.getMemoList().get(0).getSid()) - 1)));
        
        return add(spec);
    }
    
    /* (non-Javadoc)
     * @see com.geeksaga.service.MemoService#reply(com.geeksaga.domain.Issue)
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor=Exception.class)
    public Issue reply(Issue issue) throws DataAccessException {
        memoDao.updateReply(issue.getMemoList().get(0).getSid());
        
        issue.getMemoList().get(0).setSid(String.valueOf((Long.valueOf(issue.getMemoList().get(0).getSid()) - 1)));
        
        return add(issue);
    }
    
    /* (non-Javadoc)
     * @see com.geeksaga.service.BbsMemoService#reply(com.geeksaga.domain.Bbs, com.geeksaga.domain.BbsType)
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor=Exception.class)
    public Bbs reply(Bbs bbs, BbsType bbsType) throws DataAccessException {
        memoDao.updateReply(bbs.getMemoList().get(0).getSid());
        
        bbs.getMemoList().get(0).setSid(String.valueOf((Long.valueOf(bbs.getMemoList().get(0).getSid()) - 1)));
        
        return add(bbs);
    }    

    /* (non-Javadoc)
     * @see com.geeksaga.service.BbsMemoService#confirmPassword(com.geeksaga.domain.BbsMemo)
     */
    public Memo confirmPassword(Memo bbsMemo) throws DataAccessException {
        return memoDao.confirmPassword(bbsMemo);
    }
    
    /* (non-Javadoc)
     * @see com.geeksaga.service.BbsMemoService#recentList(java.util.Map)
     */
    public List<Memo> recentList(Map<String, Object> parameter) throws DataAccessException {
        return memoDao.recentList(parameter);
    }
    
    /* (non-Javadoc)
     * @see com.geeksaga.service.BbsMemoService#remove(com.geeksaga.domain.Bbs, com.geeksaga.domain.BbsType, boolean)
     */
    public Bbs remove(Bbs bbs, BbsType bbsType, boolean isManager) throws DataAccessException {
        if("A00301".equals(bbsType.getDelMemoType())) {
            bbsDao.updateCnt(bbs, Bbs.CNT_TYPE.MEMO_MINUS_CNT);
            memoDao.updateDelYn(bbs.getMemoList().get(0));
        } else if("A00302".equals(bbsType.getDelMemoType())) {
            memoDao.remove(bbs.getMemoList().get(0));
        } else if("A00303".equals(bbsType.getDelMemoType())) {
            updateContent(bbs.getMemoList().get(0), bbsType);
        } else if("A00304".equals(bbsType.getDelMemoType())) {
            if(isManager && bbsType != null && SagaConstants.USE_YES.equals(bbsType.getUserHistoryYn())) {
                updateContent(bbs.getMemoList().get(0), bbsType);
            } else {
                memoDao.remove(bbs.getMemoList().get(0));
            }
        } else if("A00305".equals(bbsType.getDelMemoType())) {
            if(isManager) {
                updateContent(bbs.getMemoList().get(0), bbsType);
            } else {
                bbsDao.updateCnt(bbs, Bbs.CNT_TYPE.MEMO_MINUS_CNT);
                memoDao.updateDelYn(bbs.getMemoList().get(0));
            }
        }
        
        return bbs;
    }
    
    /* (non-Javadoc)
     * @see com.geeksaga.service.MemoService#remove(com.geeksaga.domain.Spec, boolean)
     */
    public Spec remove(Spec spec, boolean isManager) throws DataAccessException {
		specDao.updateCnt(spec, Spec.CNT_TYPE.MEMO_MINUS_CNT);
		memoDao.updateDelYn(spec.getMemoList().get(0));
    	
    	return spec;
    }
    
    /* (non-Javadoc)
     * @see com.geeksaga.service.MemoService#remove(com.geeksaga.domain.Issue, boolean)
     */
    public Issue remove(Issue issue, boolean isManager) throws DataAccessException {
        issueDao.updateCnt(issue, Issue.CNT_TYPE.MEMO_MINUS_CNT);
        memoDao.updateDelYn(issue.getMemoList().get(0));
        
        return issue;
    }
    
    /**
     * @param bbs
     * @param bbsType
     * @return
     * @throws DataAccessException
     */
    private int updateContent(Memo bbsMemo, BbsType bbsType) throws DataAccessException {
        bbsMemo.setContent(bbsType.getDelMemoContent());
        
        return memoDao.updateContent(bbsMemo);
    }
}